$('*[data-href]').click(
      function() {
         location.href = $(this).attr('data-href');
      }
   );

$.fn.hasAttr = function(name) {
   return this.attr(name) !== undefined;
}

function array_equal(array1,array2) {
   return !(array1 < array2 || array1 > array2)
}


$.fn.keyup_change = function(callback) {
      var $this = $(this);
      var attr = 'data-previous_value';
      var callback;

      if (!$this.hasAttr(attr)) {
         $this.attr(attr,$this.val());
      }
      $this.change(callback);

      $this.keyup(
            function(e) {
               if ($this.attr(attr) != $this.val()) {
                  $this.change();
                  $this.attr(attr,$this.val());
               }
            }
         );
   }

$.fn.firstime_change = function(callback) {
      var attr = 'data-val_changed';

      if (!$this.hasAttr(attr)) {
         $this.change(callback);
         $this.change(
               function() {
                  if ($this.hasAttr(attr)) {
                     $this.unbind('change',callback);
                  }
                  $this.attr(attr,'1');
               }
            );
      }
   }

$.fn.val_sync = function(selector) {
      var $this = $(this);
      var $partner = $(selector);

      $this.keyup_change(
            function() {
               $partner.text($this.val());
            }
         );

   }

$.fn.key_combination = function (shortcut,callback) {
      var shortcut,callback;
      var keys = shortcut.split(/\s*\+\s*/);
      var empty_key_codes = {keys:[],modifiers:[]};
      var key_codes = {keys:[],modifers:[]};
      var modifier_keys = [];

      modifier_keys[16] = 'SHIFT';
      modifier_keys[17]  = 'CTRL';
      modifier_keys[18]   = 'ALT';

      var key_codes_pressed = empty_key_codes;

      for (var x in keys) {
         var key = keys[x].toUpperCase();
         if (key.length == 1) {
            key_codes.keys.push(key.charCodeAt(0));
         }
         else {
            key = modifier_keys.indexOf(key);
            key_codes.modifers.push(key);
         }
      }


      $(this).keydown(
            function(e) {
               key_codes_pressed.keys.length >= key_codes.keys.length && key_codes_pressed.keys.shift();


               if (modifier_keys[e.keyCode]) {
                  if (key_codes_pressed.modifiers.indexOf(e.keyCode) == -1) {
                     key_codes_pressed.modifiers.push(e.keyCode);
                     key_codes_pressed.modifiers.sort();
                  }
               }
               else
                  key_codes_pressed.keys.push(e.keyCode);


               if (array_equal(key_codes.keys,key_codes_pressed.keys) && array_equal(key_codes_pressed.modifiers,key_codes.modifers)) {
                  return callback(e);
               }

            }
         );

      $(this).keyup(
            function(e) {
               var modifier_index, key_index;
               modifier_index = key_codes_pressed.modifiers.indexOf(e.keyCode);
               if (modifier_index > -1) {
                  key_codes_pressed.modifiers.splice(modifier_index,1);
               }
               if (!key_codes_pressed.modifiers.length) {
                  key_codes_pressed.keys = [];
               }
            }
         );
   }

$.fn.disallow_paste = function() {
      var $this = $(this);
      $this.keyup(
            function() {
               $(this).key_combination('ctrl+v',function() { return false });
               $(this).context_menu(function(e) { return false; });
            }
         );
   }

$.fn.disallow_copy = function() {
      $(this).key_combination('ctrl+c',function(e) { try {e.preventDefault();} catch(e) {} return false; });
      $(this).context_menu(function(e) { return false; });
   }

$.fn.context_menu = function(callback) {
      var callback;
      var $this = $(this);
      return $this.bind(
            "contextmenu",
            function(e) {
               if (e.which === 3) {
                  return callback(e)
               }
            }
         );
   }

$.fn.return_key = function (callback) {
      return $(this).keydown(
            function(e) {
               if (e.keyCode === 13) {
                  return callback();
               }
            }
         );
   }
